﻿<!DOCTYPE html>
<!--[if IE]><![endif]-->
<html>
  
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Monster Stats | RogueSharp </title>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="title" content="Monster Stats - RogueSharp ">
    <meta name="generator" content="docfx 2.47.0.0">
    
    <link rel="shortcut icon" href="../images/favicon.ico">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/dracula.min.css">
    <link rel="stylesheet" href="../styles/site.css">
    <meta property="docfx:navrel" content="../toc.html">
    <meta property="docfx:tocrel" content="toc.html">
    
    
    
  </head>
  <body data-spy="scroll" data-target="#affix" data-offset="120">
    <div id="wrapper">
      <header>
        
        <div class="bg-light">
        <nav class="navbar navbar-expand-lg navbar-light bg-light container">
          
          <a class="navbar-brand" href="../index.html">
            <img id="logo" class="svg" src="../images/logo.svg" alt="RogueSharp" width="36" height="36">
          </a>
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
          </button>
        
          <div class="collapse navbar-collapse" id="navbar">
            <!--<form id="search" role="search" class="form-inline my-2 my-lg-0">
              <input id="search-query" class="form-control mr-sm-2" type="search" placeholder="Search" autocomplete="off" aria-label="Search">
            </form>-->
          </div>
        </nav>
        </div>
        
        <div class="bg-dark">
        <nav aria-label="breadcrumb" id="breadcrumb" class="container hide-when-search">
          <!--<ol class="breadcrumb">
            <li class="breadcrumb-item" aria-current="page"></li>
          </ol>-->
        </nav>
        </div>      </header>
      <div role="main" class="container body-content hide-when-search">
      <div class="row">
        
        
        <div class="sidenav hide-when-search col-md-3 pt-md-3 pb-md-3">
          <a class="btn btn-link toc-toggle d-md-none" data-toggle="collapse" data-target="#sidetoggle" href="javascript:;" aria-expanded="true" aria-controls="sidetoggle">
            Show / Hide Table of Contents
          </a>
          <div class="sidetoggle collapse" id="sidetoggle">
            <div id="sidetoc"></div>
          </div>
        </div>
        <div class="article col-md-9">
      <div class="row">
          <div class="col-lg-9">
            <article class="content wrap pt-2 pb-2" id="_content" data-uid="">
<h1 id="monster-stats">Monster Stats</h1>

<p>During this tutorial we’ll show the monster health bars in the right hand stats panel, but only when they are in line-of-sight to the player.</p>
<p><img src="../images/V3Tutorial/13_monsterstats.png" alt="Console with monster stats" title="A console with monster stats rendered"></p>
<h2 id="adding-a-drawstats-method-to-monster">Adding a DrawStats() Method to Monster</h2>
<p>As you can see in the image above, the goal for drawing monster stats is to first display the symbol of the monster in the appropriate color followed by the monster’s name. Behind the name is a health bar that will decrease based on the percentage of monster health remaining.</p>
<p>Open <code>Monster.cs</code> and add the <code>DrawStats()</code> method as follows:</p>
<pre><code class="lang-cs">public class Monster : Actor
{
  public void DrawStats( RLConsole statConsole, int position )
  {
    // Start at Y=13 which is below the player stats.
    // Multiply the position by 2 to leave a space between each stat
    int yPosition = 13 + ( position * 2 );

    // Begin the line by printing the symbol of the monster in the appropriate color
    statConsole.Print( 1, yPosition, Symbol.ToString(), Color );

    // Figure out the width of the health bar by dividing current health by max health
    int width = Convert.ToInt32( ( (double) Health / (double) MaxHealth ) * 16.0 );
    int remainingWidth = 16 - width;

    // Set the background colors of the health bar to show how damaged the monster is
    statConsole.SetBackColor( 3, yPosition, width, 1, Swatch.Primary );
    statConsole.SetBackColor( 3 + width, yPosition, remainingWidth, 1, Swatch.PrimaryDarkest );

    // Print the monsters name over top of the health bar
    statConsole.Print( 2, yPosition, $&quot;: {Name}&quot;, Swatch.DbLight );
  }
}
</code></pre>
<p>I tried to add comments to the code to help make it easier to follow along.</p>
<h2 id="updating-the-dungeonmap-draw-method">Updating the DungeonMap Draw() Method</h2>
<p>Next we need to do a bit of work to <code>DungeonMap.Draw()</code>. It needs an extra parameter <code>statConsole</code> so that when we are drawing monsters, we can also draw out their stats. It is also important that we keep a count of the number of monsters that we have drawn so far. Each time we draw a new health bar stat block for a monster we want it to be below the previous one we drew so that’s why we pass this index into <code>monster.DrawStats()</code>.</p>
<pre><code class="lang-cs">public void Draw( RLConsole mapConsole, RLConsole statConsole )
{
  // Old code
  foreach ( Cell cell in GetAllCells() )
  {
    SetConsoleSymbolForCell( mapConsole, cell );
  }

  // New code starts here ...

  // Keep an index so we know which position to draw monster stats at
  int i = 0;

  // Iterate through each monster on the map and draw it after drawing the Cells
  foreach ( Monster monster in _monsters )
  {
    monster.Draw( mapConsole, this );
    // When the monster is in the field-of-view also draw their stats
    if ( IsInFov( monster.X, monster.Y ) )
    {
      // Pass in the index to DrawStats and increment it afterwards
      monster.DrawStats( statConsole, i );
      i++;
    }
  }
}
</code></pre>
<h2 id="cleaning-up-clear-methods">Cleaning up Clear() Methods</h2>
<p>If you remember from our previous code for our <code>Draw()</code> methods on <code>DungeonMap</code> and <code>MessageLog</code> we call the <code>Clear()</code> method on the corresponding <code>RLConsole</code> every time anything changes. So what this means is that if a player or monster changes position, we <code>Clear()</code> the whole map and redraw everything. Although this may not be the most efficient way to do things, it does make the code a lot more simple and it should be good enough for our purposes.</p>
<p>The problem is that currently the <code>Clear()</code> calls are spread out in several places. Remove the <code>console.Clear()</code> calls in <code>DungeonMap.cs</code> and <code>MessageLog.cs</code></p>
<p>Then open <code>Game.cs</code> and modify the <code>OnRootConsoleRender()</code> method.</p>
<pre><code class="lang-cs">private static void OnRootConsoleRender( object sender, UpdateEventArgs e )
{
   if ( _renderRequired )
   {
      _mapConsole.Clear();
      _statConsole.Clear();
      _messageConsole.Clear();

      DungeonMap.Draw( _mapConsole, _statConsole );

      // Additional old code omitted...
   }
}
</code></pre>
<p>If you run the game now you should see the monster health bars as you find them around the map. We still can’t interact with the monsters but we will be able to soon.</p>
<h2 id="code-on-github">Code on GitHub</h2>
<p>As always the code for the tutorial series so far can be found on GitHub:</p>
<ul>
<li><a href="https://github.com/FaronBracy/RogueSharpV3Tutorial/tree/11MonsterStats">https://github.com/FaronBracy/RogueSharpV3Tutorial/tree/11MonsterStats</a></li>
</ul>
<p>Bored waiting for the next tutorial? The complete tutorial project is already finished and the source code is available on Github:</p>
<ul>
<li>Sample Roguelike game using RogueSharp and RLNet console
<ul>
<li><a href="https://github.com/FaronBracy/RogueSharpRLNetSamples">https://github.com/FaronBracy/RogueSharpRLNetSamples</a></li>
</ul>
</li>
<li>Sample Roguelike game using RogueSharp and SadConsole
<ul>
<li><a href="https://github.com/FaronBracy/RogueSharpSadConsoleSamples">https://github.com/FaronBracy/RogueSharpSadConsoleSamples</a></li>
</ul>
</li>
</ul>
</article>
            <div id="disqus_thread"></div>
            <noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
          </div>
          
          <div class="d-none d-lg-block col-md-3" role="complementary">
            <div class="sideaffix pt-3 pb-3">
              <div class="contribution">
                <ul class="nav">
                  <li>
                    <a href="https://github.com/FaronBracy/RogueSharp.Documentation/blob/master/articles/13_monster_stats.md/#L1" class="contribution-link text-info" title="Improve this Doc">
                    <i class="fal fa-edit fa-fw"></i>
                    <span>Improve this Doc</span>
                    </a>
                  </li>
                </ul>
              </div>
              <!--<div class="github-links">
                  <a class="github-button" href="https://github.com/fszlin/certes" data-icon="octicon-star" data-size="large" data-show-count="true" aria-label="Star fszlin/certes on GitHub">Star</a>
              </div>-->
              <nav class="hidden-print affix mt-2" id="affix">
              <!-- <p><a class="back-to-top" href="#top">Back to top</a><p> -->
              </nav>
            </div>
          </div>
          </div>
        </div>
      </div>
      </div>
      
      <footer class="bg-secondary">
        <!--<div class="grad-bottom"></div>-->
        <div class="footer bg-secondary">
          <div class="container">
          <div class="d-flex">
            <div class="p-2 flex-grow-1 text-white">
            <a class="text-white" href="https://github.com/FaronBracy/RogueSharp">RogueSharp &copy; 2014-2020 Faron Bracy</a>
            
            </div>
            <div class="p-2">
              <a class="text-white" href="#top">Back to top</a>
            </div>
          </div>
          </div>
        </div>
      </footer>
    </div>
    
    <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/anchor-js/4.1.0/anchor.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/dos.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/powershell.min.js"></script>
    <script type="text/javascript" src="../styles/docfx.js"></script>
  </body>
</html>
